#include "InternalConsole.h"
#include "Sheet.h"
#include "internalconsolelua.h"
#include "ObjectFactory.h"

RegisterCppObj<InternalConsole> g_register_internalconsole_object;

void SimpleConsoleHelper::sendMessage(const std::string& message)
{
	_outMessages.push_back(message);
}

std::vector<std::string> SimpleConsoleHelper::receiveMessages()
{
	std::vector<std::string> temp = _cmdMessages;
	_cmdMessages.clear();
	return temp;
}

std::vector<std::string> SimpleConsoleHelper::getOutputMessages()
{
	std::vector<std::string> temp = _outMessages;
	_outMessages.clear();
	return temp;
}

void SimpleConsoleHelper::executeCommand(std::string& command)
{
	_cmdMessages.push_back(command);
}

bool SimpleConsoleHelper::hasOutput()
{
	return _outMessages.size() > 0;
}

InternalConsole::InternalConsole()
{
	_simpleConsole = new SimpleConsoleHelper;
}

InternalConsole::~InternalConsole()
{
	delete _simpleConsole;
}

void InternalConsole::attach(int sheetId, int chanId)
{
	detach();
	_attachedSheet = sheetId;
	_attachedChannel = chanId;
	getSheet()->ultra()->addConsole(_simpleConsole, sheetId, chanId);
}

void InternalConsole::detach()
{
	getSheet()->ultra()->removeConsole(_simpleConsole);
}

void InternalConsole::addPrinter(AnyAOPtr printer)
{
	_printers.push_back(printer);
}

void InternalConsole::removePrinter(AnyAOPtr printer)
{
	for(std::vector<AnyAOPtr>::iterator i = _printers.begin(); i != _printers.end();)
	{
		if(*i == printer)
		{
			i = _printers.erase(i);
		}
		else
		{
			++i;
		}
	}
}

void InternalConsole::executeCommand(std::string& cmd)
{
	_simpleConsole->executeCommand(cmd);
}

// Genero AbstractObject stuff below

// Return the c++ type id
int InternalConsole::getCppTypeId()
{
	return 3716312;
}

// Returns whether this can be cast to a given type
bool InternalConsole::isType(int id)
{
	return false;
}

// Return the c++ type as a string 
std::string InternalConsole::getCppTypeName()
{
	return "InternalConsole";
}

// returns a description of this thing
std::string InternalConsole::getDescription()
{
	return "Internal AbstractObject based way to access the consoles";
}

// create another one of these
AbstractObject* InternalConsole::newInstance()
{
	return new InternalConsole;
}

// init & update
void InternalConsole::init()
{
	// nothing special
}

void InternalConsole::update(double dt)
{
	if(_simpleConsole->hasOutput())
	{
		std::vector<std::string> msgs = _simpleConsole->getOutputMessages();
		for(int j = 0; j < msgs.size(); ++j)
		{
			IData tempid;
			tempid.sets(tempid.named("textLine"), msgs[j]);
			for(int i = 0; i < _printers.size(); ++i)
			{
				if(*(_printers[i]))
					_printers[i]->interact("consoleOutput", tempid);
			}
		}
	}
}

// push its static functions into the given lua table
void InternalConsole::pushStaticFuncs(lua_State* L)
{
	// push superclass static functions...
	AbstractObject::pushStaticFuncs(L);

	// blargh
	InternalConsoleLua::pushStaticFuncs(L);
}